class FNFALACOGFire extends SRHighROFFire;

var float Penetration;

var bool bIsCritical;
var float BaseCritStrikeChance,BaseCritDamageMod;
var int MaxPenetrations;

function DoTrace(Vector Start, Rotator Dir)
{
	local Vector X,Y,Z, End, HitLocation, HitNormal, ArcEnd;
	local Actor Other;
	local byte HitCount,HCounter;
	local float HitDamage;
	local array<int>	HitPoints;
	local KFPawn HitPawn;
	local array<Actor>	IgnoreActors;
	local Actor DamageActor;
	local int i;
	
	HitDamage = SetShootParams();

	MaxRange();

	Weapon.GetViewAxes(X, Y, Z);
	if ( Weapon.WeaponCentered() )
	{
		ArcEnd = (Instigator.Location + Weapon.EffectOffset.X * X + 1.5 * Weapon.EffectOffset.Z * Z);
	}
	else
    {
        ArcEnd = (Instigator.Location + Instigator.CalcDrawOffset(Weapon) + Weapon.EffectOffset.X * X +
		 Weapon.Hand * Weapon.EffectOffset.Y * Y + Weapon.EffectOffset.Z * Z);
    }

	X = Vector(Dir);
	End = Start + TraceRange * X;
	HitDamage = DamageMax;
	While( (HitCount++)<3 )
	{
        DamageActor = none;

		Other = Instigator.HitPointTrace(HitLocation, HitNormal, End, HitPoints, Start,, 1);
		if( Other==None )
		{
			Break;
		}
		else if( Other==Instigator || Other.Base == Instigator )
		{
			IgnoreActors[IgnoreActors.Length] = Other;
			Other.SetCollision(false);
			Start = HitLocation;
			Continue;
		}

		if( ExtendedZCollision(Other)!=None && Other.Owner!=None )
		{
            IgnoreActors[IgnoreActors.Length] = Other;
            IgnoreActors[IgnoreActors.Length] = Other.Owner;
			Other.SetCollision(false);
			Other.Owner.SetCollision(false);
			DamageActor = Pawn(Other.Owner);
		}

		if ( !Other.bWorldGeometry && Other!=Level )
		{
			HitPawn = KFPawn(Other);

	    	if ( HitPawn != none )
	    	{
                 // Hit detection debugging
				 /*log("PreLaunchTrace hit "$HitPawn.PlayerReplicationInfo.PlayerName);
				 HitPawn.HitStart = Start;
				 HitPawn.HitEnd = End;*/
                 if(!HitPawn.bDeleteMe)
				 	HitPawn.ProcessLocationalDamage(int(HitDamage), Instigator, HitLocation, Momentum*X,DamageType,HitPoints);

                 // Hit detection debugging
				 /*if( Level.NetMode == NM_Standalone)
				 	  HitPawn.DrawBoneLocation();*/

                IgnoreActors[IgnoreActors.Length] = Other;
                IgnoreActors[IgnoreActors.Length] = HitPawn.AuxCollisionCylinder;
    			Other.SetCollision(false);
    			HitPawn.AuxCollisionCylinder.SetCollision(false);
    			DamageActor = Other;
			}
            else
            {
    			if( KFMonster(Other)!=None )
    			{
                    IgnoreActors[IgnoreActors.Length] = Other;
        			Other.SetCollision(false);
        			DamageActor = Other;
    			}
    			else if( DamageActor == none )
    			{
                    DamageActor = Other;
    			}
				if ( bIsCritical && DKMonster(Other) != none )
				{
					DamageType = class'DamTypeGunfighterCriticalStrike';
					DKMonster(Other).HeadshotMod = class<KFWeaponDamageType>(default.DamageType).default.HeadShotDamageMult;
				}
				else
				{
					DamageType = default.DamageType;
				}
    			Other.TakeDamage(int(HitDamage), Instigator, HitLocation, Momentum*X, DamageType);
			}
			if( (HCounter++)>=MaxPenetrations || Pawn(DamageActor)==None )
			{
				Break;
			}
			HitDamage *= Penetration;
			Start = HitLocation;
		}
		else if ( HitScanBlockingVolume(Other)==None )
		{
			if( KFWeaponAttachment(Weapon.ThirdPersonActor)!=None )
		      KFWeaponAttachment(Weapon.ThirdPersonActor).UpdateHit(Other,HitLocation,HitNormal);
			Break;
		}
	}

    // Turn the collision back on for any actors we turned it off
	if ( IgnoreActors.Length > 0 )
	{
		for (i=0; i<IgnoreActors.Length; i++)
		{
            IgnoreActors[i].SetCollision(true);
		}
	}
}

function int SetShootParams()
{
	local int ret;
	local SRPlayerReplicationInfo SRPRI;
	local float Chance;
	
	ret = DamageMax;
	SRPRI = SRPlayerReplicationInfo(Weapon.Instigator.PlayerReplicationInfo);
	if ( SRPRI != none )
	{
		Chance = BaseCritStrikeChance + class<SRVeterancy>(SRPRI.ClientVeteranSkill).Static.CritStrikeChance(SRPRI);
	}
	else
	{
		Chance = BaseCritStrikeChance;
	}
	
	if ( FRand() < Chance )
	{
		bIsCritical = true;

		if ( SRPRI != none )
		{
			ret *= BaseCritDamageMod * class<SRVeterancy>(SRPRI.ClientVeteranSkill).Static.CritDamageModifier(SRPRI);
		}
		else
		{
			ret *= BaseCritDamageMod;
		}
		
		MaxPenetrations = default.MaxPenetrations + 4;
		Penetration = default.Penetration + 0.5;
	}
	else
	{
		bIsCritical = false;
	}
	
	return ret;
}

defaultproperties
{
	 BaseCritStrikeChance = -0.05
	 MaxPenetrations = 4

	 bWaitForRelease=True
	 Penetration = 0.70

     FireEndSoundRef="KF_FNFALSnd.FNFAL_Fire_Loop_End_M"
     FireEndStereoSoundRef="KF_FNFALSnd.FNFAL_Fire_Loop_End_S"
     AmbientFireSoundRef="KF_FNFALSnd.FNFAL_Fire_Loop"
     RecoilRate=0.10
     maxVerticalRecoilAngle=130
     maxHorizontalRecoilAngle=95
     ShellEjectClass=Class'KFMod.KFShellEjectFAL'
     ShellEjectBoneName="Shell_eject"
     bRandomPitchFireSound=False
     FireSoundRef="msp.FalFire2"
     StereoFireSoundRef="msp.FnFire1"
     NoAmmoSoundRef="KF_SCARSnd.SCAR_DryFire"
     DamageType=Class'DamTypeFnFal'
     DamageMin=150
     DamageMax=150
     Momentum=8500.000000
     FireRate=0.13
     AmmoClass=Class'FnFalACOGAmmo'
     ShakeRotMag=(X=80.000000,Y=80.000000,Z=450.000000)
     ShakeRotRate=(X=7500.000000,Y=7500.000000,Z=7500.000000)
     ShakeRotTime=0.650000
     ShakeOffsetMag=(X=6.000000,Y=3.000000,Z=8.500000)
     ShakeOffsetRate=(X=1000.000000,Y=1000.000000,Z=1000.000000)
     ShakeOffsetTime=1.150000
     BotRefireRate=0.990000
     FlashEmitterClass=Class'ROEffects.MuzzleFlash1stSTG'
     aimerror=42.000000
     Spread=0.008500
     SpreadStyle=SS_Random
}
